package querylayer

import (
	"database/sql"
	"encoding/json"
	"fmt"

	_ "github.com/lib/pq"
	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

// 定义一个通用接口
type DBInsertable interface {
	Insert(db *sql.DB) error
}

// 1. prescription
type Prescription struct {
	PresHeadID string `json:"PresHeadID"`
	PatientID  string `json:"PatientID"`
	MemberID   int    `json:"MemberID"`
	PatListID  int    `json:"PatListID"`
	PresType   int16  `json:"PresType"`
	WorkID     int    `json:"WorkID"`
}

func (p *Prescription) Insert(db *sql.DB) error {
	fmt.Println("Inserting prescription")
	query := `INSERT INTO prescription (PresHeadID, PatientID, MemberID, PatListID, PresType, WorkID) VALUES ($1, $2, $3, $4, $5, $6)`
	_, err := db.Exec(query, p.PresHeadID, p.PatientID, p.MemberID, p.PatListID, p.PresType, p.WorkID)
	if err != nil {
		fmt.Println("failed to insert prescription: %v", err)
		return fmt.Errorf("failed to insert prescription: %v", err)
	}
	return err
}

// 2. prescription_detail
type PrescriptionDetail struct {
	PresDetailID    int     `json:"PresDetailID"`
	PresHeadID      string  `json:"PresHeadID"`
	PresNO          int     `json:"PresNO"`
	ItemID          int     `json:"ItemID"`
	ItemName        string  `json:"ItemName"`
	Spec            string  `json:"Spec"`
	Dosage          float64 `json:"Dosage"`
	DosageUnit      string  `json:"DosageUnit"`
	IsReimbursement int16   `json:"IsReimbursement"`
}

func (p *PrescriptionDetail) Insert(db *sql.DB) error {
	query := `INSERT INTO prescription_detail (PresDetailID, PresHeadID, PresNO, ItemID, ItemName, Spec, Dosage, DosageUnit, IsReimbursement) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`
	_, err := db.Exec(query, p.PresDetailID, p.PresHeadID, p.PresNO, p.ItemID, p.ItemName, p.Spec, p.Dosage, p.DosageUnit, p.IsReimbursement)
	if err != nil {
		fmt.Println("failed to insert prescription_detail: %v", err)
	}
	return err
}

// 3. prescription_signature
type PrescriptionSignature struct {
	ID               int    `json:"ID"`
	TargetNo         int    `json:"TargetId"`
	SignatureResults string `json:"SignatureResults"`
	OpenId           string `json:"OpenId"`
	SignFlag         int    `json:"SignFlag"`
	SignEmpId        string `json:"SignEmpId"`
	CreateDate       string `json:"CreateDate"`
}

func (p *PrescriptionSignature) Insert(db *sql.DB) error {
	query := `INSERT INTO prescription_signature (ID, TargetId, SignatureResults, OpenId, SignFlag, SignEmpId, CreateDate) VALUES ($1, $2, $3, $4, $5, $6, $7)`
	_, err := db.Exec(query, p.ID, p.TargetNo, p.SignatureResults, p.OpenId, p.SignFlag, p.SignEmpId, p.CreateDate)
	if err != nil {
		fmt.Println("failed to insert prescription_signature: %v", err)
	}
	return err
}

// 4. prescription_audit
type PrescriptionAudit struct {
	ID                  int    `json:"ID"`
	PresHeadID          string `json:"PresHeadID"`
	PresNO              int    `json:"PresNO"`
	PresAuditStatus     int    `json:"PresAuditStatus"`
	PresAuditResult     string `json:"PresAuditResult"`
	PresAuditContent    string `json:"PresAuditContent"`
	PresAuditPharmacist string `json:"PresAuditPharmacist"`
	PresAuditDate       string `json:"PresAuditDate"`
	PresDocUpdateStatus int    `json:"PresDocUpdateStatus"`
	PresAuditSureStatus int    `json:"PresAuditSureStatus"`
}

func (p *PrescriptionAudit) Insert(db *sql.DB) error {
	query := `INSERT INTO prescription_audit (ID, PresHeadID, PresNO, PresAuditStatus, PresAuditResult, PresAuditContent, PresAuditPharmacist, PresAuditDate, PresDocUpdateStatus, PresAuditSureStatus) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)`
	_, err := db.Exec(query, p.ID, p.PresHeadID, p.PresNO, p.PresAuditStatus, p.PresAuditResult, p.PresAuditContent, p.PresAuditPharmacist, p.PresAuditDate, p.PresDocUpdateStatus, p.PresAuditSureStatus)
	if err != nil {
		fmt.Println("failed to insert prescription_audit: %v", err)
	}
	return err
}

// 5. visit_record
type VisitRecord struct {
	ID                    int    `json:"ID"`
	PresHeadID            string `json:"PresHeadID"`
	PatientID             string `json:"PatientID"`
	DelFlag               int    `json:"del_flag"`
	Remarks               string `json:"remarks"`
	Doctors               string `json:"doctors"`
	Advice                string `json:"advice"`
	VisitTime             string `json:"visit_time"`
	HospitalDepartmentsID string `json:"hospital_departments_id"`
	DepartmentsName       string `json:"departments_name"`
}

func (v *VisitRecord) Insert(db *sql.DB) error {
	query := `INSERT INTO visit_record (ID, PresHeadID, PatientID, del_flag, remarks, doctors, advice, visit_time, hospital_departments_id, departments_name) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)`
	_, err := db.Exec(query, v.ID, v.PresHeadID, v.PatientID, v.DelFlag, v.Remarks, v.Doctors, v.Advice, v.VisitTime, v.HospitalDepartmentsID, v.DepartmentsName)
	if err != nil {
		fmt.Println("failed to insert visit_record: %v", err)
	}
	//fmt.Println("visit_record: %v", err)
	return err
}

// 6. ecg_sequence
type EcgSeries struct {
	ID              int64  `json:"ID"`
	PatientID       string `json:"PatientID"`
	MedicalRecordID int64  `json:"MedicalRecordID"`
}

func (e *EcgSeries) Insert(db *sql.DB) error {
	query := `INSERT INTO ecg_series (ID, PatientID, VisitRecordID) VALUES ($1, $2, $3)`
	_, err := db.Exec(query, e.ID, e.PatientID, e.MedicalRecordID)
	if err != nil {
		fmt.Println("failed to insert ecg_series: %v", err)
	}
	return err
}

// 7. medical_image
type MedicalImage struct {
	ID              int64  `json:"ID"`
	PatientID       string `json:"PatientID"`
	MedicalRecordID int64  `json:"MedicalRecordID"`
}

func (m *MedicalImage) Insert(db *sql.DB) error {
	query := `INSERT INTO ct_image (ID, PatientID, VisitRecordID) VALUES ($1, $2, $3)`
	_, err := db.Exec(query, m.ID, m.PatientID, m.MedicalRecordID)
	if err != nil {
		fmt.Println("failed to insert ecg_series: %v", err)
	}
	return err
}

// 统一接口函数
func InsertDongRuanDiscription(db *sql.DB, fileData *tmproto.FileData) error {
	category := fileData.FileCategory
	jsonDesc := fileData.Description

	var obj DBInsertable
	switch category {
	case tmproto.FileCategory_Prescription:

		var data Prescription
		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data

	case tmproto.FileCategory_Prescription_Detail:
		var data PrescriptionDetail

		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data

	case tmproto.FileCategory_prescription_Audit:
		var data PrescriptionAudit
		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data

	case tmproto.FileCategory_prescription_Signature:
		var data PrescriptionSignature

		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data

	case tmproto.FileCategory_Visit_Record:
		var data VisitRecord

		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data

	case tmproto.FileCategory_Ecg_Sequence:
		var data EcgSeries
		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data
	case tmproto.FileCategory_Medical_Image:
		var data MedicalImage
		if err := json.Unmarshal(jsonDesc, &data); err != nil {
			fmt.Println("failed to unmarshal jsonDesc:", err)
			return err
		}
		obj = &data

	default:
		return fmt.Errorf("unsupported file_category: %s", category)
	}

	return obj.Insert(db)
}
